package com.my.aslife.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.my.aslife.mapper.AddressMapper;
import com.my.aslife.mapper.TaskMapper;
import com.my.aslife.mapper.UserMapper;
import com.my.aslife.module.common.*;
import com.my.aslife.mapper.DemandMapper;
import com.my.aslife.module.entity.*;
import com.my.aslife.module.entity.bo.DemandUpdateBo;
import com.my.aslife.module.entity.dtos.*;
import com.my.aslife.module.entity.vo.OrderVo;
import com.my.aslife.service.*;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.my.aslife.utils.SnowFlakeUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author jobob
 * @since 2022-12-12
 */
@Service
@Slf4j
public class DemandServiceImpl extends ServiceImpl<DemandMapper, Demand> implements DemandService {

    @Autowired
    private AddressService addressService;

    @Autowired
    private AddressMapper addressMapper;

    @Autowired
    private TaskService taskService;

    @Autowired
    private OrdersService ordersService;

    @Autowired
    private DemandMapper demandMapper;

    @Autowired
    private TaskMapper taskMapper;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private IUserService userService;

    @Autowired
    private UserMapper userMapper;

    @Override
    @Transactional
    public ResponseResult insertDemandInfo(DemandAddDto demandAddDto) {

        // 线上判断金额是否充足
        if (demandAddDto.getPayType() == 1) {
            User user = userService.queryUserById(UserIdThreadLocal.get());
            Integer totalMoney = demandAddDto.getMoney() + demandAddDto.getEmergencyFee();
            if (user.getMoney() < totalMoney) {
                return ResponseResult.failed(ErrorCode.MONEY_NOT_GOOD_ENOUGH);
            }

            DeductMoneyDto deductMoneyDto = new DeductMoneyDto();
            deductMoneyDto.setMoney(totalMoney);
            deductMoneyDto.setUid(Long.valueOf(UserIdThreadLocal.get()));

            TxMoney txMoney = new TxMoney();
            txMoney.setId(SnowFlakeUtil.getId());
            txMoney.setUid(Long.valueOf(UserIdThreadLocal.get()));
            txMoney.setMoney(totalMoney);
            txMoney.setCreateTime(new Date());
            txMoney.setFinishTime(new Date());
            deductMoneyDto.setTxMoney(txMoney);
            userService.deductMoney(deductMoneyDto);
        }

        Long snowId = SnowFlakeUtil.getId();

        Address address = demandAddDto.getAddress();
        address.setUid(demandAddDto.getUid());
        address.setNickName(address.getUserName());
        address.setCreateTime(new Date());
        address.setDemandKey(snowId);

        // 保存用户地址
        addressService.insertAddress(address);

        Demand demand = new Demand();
        BeanUtils.copyProperties(demandAddDto, demand);
        demand.setAddress(demandAddDto.getAddress().getDetailInfo());
        demand.setCreateTime(new Date());
        demand.setUpdateTime(new Date());
        demand.setAddressKey(snowId);
        demand.setStatus(Short.valueOf("" + DemandStatus.REVIEW.getType()));
        //0 线下 1 线上
        Short payType = demand.getPayType();
        //0 普通 1 加急
        Short runType = demand.getRunType();
        // 计算 配送员显示状态
        int demandRunnerStatusNum = 0;
        if (payType == 1) {
            demandRunnerStatusNum += DemandRunnerStatus.ONLINE.getCode();
        } else {
            demandRunnerStatusNum += DemandRunnerStatus.OFFLINE.getCode();
        }
        if (runType == 1) {
            demandRunnerStatusNum = demandRunnerStatusNum * 10 + DemandRunnerStatus.URGENT.getCode();
        }
        demand.setRunnerStatus(new Short(demandRunnerStatusNum+""));

        // 保存需求信息
        save(demand);

        // 异步检查需求是否有敏感词
        checkDemandText(demand);

        return ResponseResult.ok();
    }

    @Async
    void checkDemandText(Demand demand) {
        Task task = new Task();
        task.setTaskId(demand.getAddressKey());
        task.setStatus(demand.getStatus());
        task.setText(demand.getContext());
        taskService.saveTask(task);
    }

    @Override
    public ResponseResult getDemandInfoForList(Integer uid) {

        LambdaQueryWrapper<Demand> lqwDemand = new LambdaQueryWrapper<>();
        lqwDemand.eq(Demand::getUid, uid).orderByDesc(Demand::getCreateTime);
        List<Demand> listDemand = this.list(lqwDemand);

        return ResponseResult.ok(listDemand);
    }

    @Override
    public ResponseResult queryDemandInfo(DemandQueryDto demandQueryDto) {
        LambdaQueryWrapper<Demand> lqwDemand = new LambdaQueryWrapper<>();
        lqwDemand.eq(Demand::getAddressKey, demandQueryDto.getAddressKey());
        Demand demand = getOne(lqwDemand);

        ResponseResult responseResult = ordersService.queryOrderByOrderId(demand.getAddressKey());
        OrderVo orderVo = new OrderVo(demand, (Orders) responseResult.getData());

        return ResponseResult.ok(orderVo);
    }

    @Override
    @Transactional
    public ResponseResult updateAddress(DemandUpdateDto demandUpdateDto) {
        // 用户只能修改一次
        String changeAddressKey = RedisConstant.USER_CHANGE_ADDRESS + demandUpdateDto.getAddressKey();
        String flag = stringRedisTemplate.opsForValue().get(changeAddressKey);
        if (flag != null) {
            return ResponseResult.failed(ErrorCode.NOT_CHANGE_ADDRESS);
        }
        // 修改地址
        addressMapper.addressMapper(demandUpdateDto.getAddressKey());
        addressService.save(demandUpdateDto.getAddress());
        // 修改需求
        DemandUpdateBo demandUpdateBo = new DemandUpdateBo();
        demandUpdateBo.setAddressKey(demandUpdateDto.getAddressKey());
        demandUpdateBo.setAddress(demandUpdateDto.getAddress().getDetailInfo());
        Date updateTime = new Date();
        demandMapper.updateAddress(demandUpdateBo, updateTime);
        stringRedisTemplate.opsForValue().set(changeAddressKey, "true" , RedisConstant.ONE_DAY, TimeUnit.DAYS);
        return ResponseResult.ok();
    }

    @Override
    @Transactional
    public ResponseResult deleteDemandByAddressKey(String addressKey) {
        demandMapper.deleteDemandByAddressKey(addressKey);
        taskMapper.deleteDemandByTaskId(addressKey);
        return ResponseResult.ok();
    }

    @Override
    public ResponseResult getPassDemandList(Long uid) {
        // 1 已发布
        List<Demand> list = demandMapper.getPassDemandList(uid);

        String key = RedisConstant.USER_RUNNER_DEMAND_LIST + UserIdThreadLocal.get();
        Long size = stringRedisTemplate.opsForZSet().size(key);

        if (size != null && size > 0) {
            Set<String> range = stringRedisTemplate.opsForZSet().range(key, 0, size);
            List<Demand> listDemand2 = demandMapper.queryDemandInfoByAddressKeys(range);
            list.addAll(listDemand2);
        }
        return ResponseResult.ok(list);
    }

    /**
     * 跑腿者接受任务，并且生成订单。
     * @param demandAcceptDto demandAcceptDto
     * @return
     */
    @Override
    public ResponseResult acceptDemand(DemandAcceptDto demandAcceptDto) {

        return null;
    }

    @Override
    public ResponseResult queryDemandByDemandKey(Long demandKey) {
        LambdaQueryWrapper<Demand> lqw = new LambdaQueryWrapper<>();
        lqw.eq(Demand::getAddressKey, demandKey);

        return ResponseResult.ok(getOne(lqw));
    }

    @Override
    public ResponseResult setDemandStatusIsAccepted(Long demandKey) {
        demandMapper.setDemandStatusIsAccepted(demandKey);
        return ResponseResult.ok();
    }

    @Override
    public ResponseResult updateOrderStatusIsFinish(String url, Long orderId) {
        demandMapper.updateOrderStatusIsFinish(url, orderId);
        return ResponseResult.ok();
    }

    @Override
    public ResponseResult getAllDemandInfo(PageRequestVo pageRequestVo) {

        int c = pageRequestVo.getCurrent();
        int p = pageRequestVo.getPageSize();
        int start = (c - 1) * p;
        List<Demand> demandList = demandMapper.getAllDemandInfo(start, p);
        return ResponseResult.ok(demandList, count());
    }

    @Override
    public void txMoney(Long taskId) {
        LambdaQueryWrapper<Demand> lqw = new LambdaQueryWrapper<>();
        lqw.eq(Demand::getAddressKey, taskId);
        Demand one = getOne(lqw);
        if (one == null) {
            log.error("金额恢复失败，请人工处理 => {}", taskId);
            return;
        }
        User user = new User();
        user.setUid(one.getUid());
        user.setMoney(one.getEmergencyFee() + one.getMoney());
        userService.txMoney(user);

    }

    @Override
    public ResponseResult runOk(Demand demand) {
        demandMapper.runOk(demand);
        // 配送者加钱
        Long addressKey = demand.getAddressKey();
        LambdaQueryWrapper<Demand> lqw = new LambdaQueryWrapper<>();
        lqw.eq(Demand::getAddressKey, addressKey);
        Demand one = getOne(lqw);
        userService.jiaMoney((one.getEmergencyFee() + one.getMoney()));

        return ResponseResult.ok();
    }

    @Override
    public ResponseResult adminOk(Long orderId) {
        demandMapper.checkDemandContext(1, Long.valueOf(UserIdThreadLocal.get()), orderId, null);
        return ResponseResult.ok();
    }
}
